#include "Expand/Plugins/AuthPlugin.h"
#include <fstream>
#include "Utils/BinaryIO.h"
#include "Log.h"
#include "Network/PackageManager.h"
#include "Network/Packages/MessagePackage.h"

#include "Player/PlayerData.h"
#include "Subsystems/SubsystemPlayers.h"

#include "GameSingleton.h"

namespace PocketSurvival
{
    
    const std::string &AuthPlugin::getPluginName()
    {
        static const std::string pluginName = "服务器权限插件";
        return pluginName;
    }
    const std::string &AuthPlugin::getIntroduce()
    {
        static const std::string introduce = "\n/auth user (在线玩家) (等级) - 设置玩家权限等级\n/auth guid (在线玩家guid) (等级) - 直接修改对应guid的权限等级";
        return introduce;
    }
    uint32_t AuthPlugin::getUseAuthLevel()
    {
        return 100;
    }
    AuthDisplayType AuthPlugin::getDisplayType()
    {
        return AuthDisplayType::Authority;
    }

    void AuthPlugin::processCmd(ChatObj &chatObj, std::vector<std::string> &cmdDataVec)
    {
        if(cmdDataVec.size() >= 4)
        {
            uint32_t level = atoi(cmdDataVec[3].c_str());
            if(cmdDataVec[1] == "user")
            {
                std::vector<std::shared_ptr<PlayerData>> playerVec;
                GameSingleton::singletonPtr->getSingleton<SubsystemPlayers>()->getAllPlayerData(playerVec);
                std::shared_ptr<PlayerData> targetPlayer = nullptr;
                uint32_t findCount = 0;
                for(std::shared_ptr<PlayerData> &playerData : playerVec)
                {
                    if(playerData->username == cmdDataVec[2])
                    {
                        targetPlayer = playerData;
                        findCount++;
                    }
                }
                if(targetPlayer != nullptr)
                {
                    if(findCount > 1)
                    {
                        chatObj.sendMessage("auth", fmt::format("存在多个同名 {} 的玩家，需要手动使用GUID赋予权限等级", cmdDataVec[2]));
                    }
                    else
                    {
                        std::lock_guard<std::mutex> lk(m_mapMutex);
                        m_authMap[targetPlayer->playerGuid] = level;
                        chatObj.sendMessage("auth", fmt::format("成功将 {} 的权限等级设置为: {}", cmdDataVec[2], level));

                        GameSingleton::packageManager->addSendPackageToQueue(std::make_shared<MessagePackage>(fmt::format("管理员将你的权限等级改为 {}", level), targetPlayer->client));
                    }
                }
                else
                {
                    chatObj.sendMessage("auth", fmt::format("玩家 {} 貌似不在线", cmdDataVec[2]));
                }
                return;
            }

            
            if(cmdDataVec[1] == "guid")
            {
                std::shared_ptr<PlayerData> targetPlayer = GameSingleton::singletonPtr->getSingleton<SubsystemPlayers>()->getPlayerDataByGuid(GameGuid(cmdDataVec[2]));
                if(targetPlayer != nullptr)
                {
                    std::lock_guard<std::mutex> lk(m_mapMutex);
                    m_authMap[targetPlayer->playerGuid] = level;
                    chatObj.sendMessage("auth", fmt::format("成功将 {} 的权限等级设置为: {}", targetPlayer->username, level));

                    GameSingleton::packageManager->addSendPackageToQueue(std::make_shared<MessagePackage>(fmt::format("管理员将你的权限等级改为 {}", level), targetPlayer->client));
                }
                else
                {
                    chatObj.sendMessage("auth", fmt::format("GUID为 {} 的玩家貌似不在线", cmdDataVec[2]));
                }
                return;
            }
        }
        chatObj.sendMessage("auth", getIntroduce());
    }

    uint32_t AuthPlugin::getLevelByGuid(const GameGuid& guid)
    {
        std::lock_guard<std::mutex> lk(m_mapMutex);
        auto it = m_authMap.find(guid);
        if(it != m_authMap.end())
        {
            return it->second;
        }
        return 0;
    }

    void AuthPlugin::getCmds(std::vector<std::string> &cmdVec)
    {
        cmdVec.push_back("/auth");
    }

    void AuthPlugin::load()
    {
        std::lock_guard<std::mutex> lk(m_mapMutex);
        std::ifstream stream;
        stream.open("./Server/auth.json");
        if(stream.is_open())
        {
            nlohmann::json jsonData;
            stream >> jsonData;

            Utils::GetJsonValue<std::map<GameGuid, uint32_t>>(jsonData, m_authMap, "data", std::map<GameGuid, uint32_t>());
        }
        stream.close();
    }

    void AuthPlugin::save()
    {
        std::lock_guard<std::mutex> lk(m_mapMutex);
        std::map<GameGuid, uint32_t> authMapCopy;
        for(const auto &pair : m_authMap)
        {
            if(pair.second > 0)
            {
                authMapCopy[pair.first] = pair.second;
            }
        }
        m_authMap.swap(authMapCopy);

        nlohmann::json jsonData = {{"data",m_authMap}};
        Utils::SaveTextFile("./Server/auth.json", jsonData.dump());
    }
} // namespace PocketSurvival
